﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using NumericalMethods;
using NumericalMethods.FourthBlog;

using MathExpr;


namespace NumericalMethods
{
    public class NewtonRaphson1
    {
        private Matrix _jacobian;
        
        private Matrix _functionMatrix;
        
        private Matrix _x0;
        
        private Derivatives _derivatives;

        private List<Parameter> _parameters = new List<Parameter>();

        List<Node> listanudos1 = new List<Node>();
        Evaluator ev1 = new Evaluator();
        List<Double> listaresultados1 = new List<Double>();

        List<String> variable1 = new List<String>();

        Int16 numberOfFunctions;

        public NewtonRaphson1(Int16 numeroecuaciones,List<Parameter> parameters, int numberOfDerivativePoints, List<Node> listanudos, List<String> variable)
        {
            variable1 = variable;
            listanudos1 = listanudos;
            _parameters = parameters;
            numberOfFunctions = numeroecuaciones;
            int numberOfParameters = _parameters.Count;

            Debug.Assert(numberOfParameters == numberOfFunctions);

            _derivatives = new Derivatives(numberOfDerivativePoints);

            _jacobian = new Matrix(numberOfFunctions, numberOfParameters);
            _functionMatrix = new Matrix(numberOfFunctions, 1);
            _x0 = new Matrix(numberOfFunctions, 1);

            //Siguiente paso enviar los valores inciales de las variables
            //Bucle para asignar los valores inciales alas variables
         }

        // Primero se llama a este Constructor de la Clase NewtonRaphson, que a su vez llama al constructor sobrecargado enviándole además el numberOfDerivativePoints=3
        //El 3 indica el numberOfDerivativePoints por defecto. 
        public NewtonRaphson1(Int16 numeroecuaciones,List<Parameter> parameters, List<Node> listanudos, List<String> variable)
            : this(numeroecuaciones,parameters, 3, listanudos,variable)
        {
        }

        public void destructor()
        {

            for (int i = 0; i < numberOfFunctions; i++)
            {
                _parameters.RemoveAt(0);
            }  

        }
        public void Iterate()
        {
            int numberOfParameters = _parameters.Count;

            //Bucle para actualizar los valores donde queremos calcular f(xi)
            for (int i = 0; i < numberOfFunctions; i++)
            {
                ev1[variable1[i]] = _parameters[i].Value;
            }
            for (int i = 0; i < numberOfFunctions; i++)
            {
               // _functionMatrix[i, 0] = _functions[i]();
               
                //Codigo de prueba de LUIS COCO 
                //El siguiente paso es enviar las variables, sus nombres y valores
                //listaresultados1.Add(0);
                //listaresultados1[i] = ev1.Evaluate(listanudos1[i]);
                _functionMatrix[i, 0] = ev1.Evaluate(listanudos1[i]);
                _x0[i, 0] = _parameters[i];
            }
            
            for (int i = 0; i < numberOfFunctions; i++)
            {

                for (int j = 0; j < numberOfParameters; j++)
                {
                    //El 1 en los argumentos de la función ComputePartialDerivative indica que las derivadas a calcular son de primer orden.
                    //Envimos como argumentos las funciones _functions y las variables de las ecuaciones _parameters
                    _jacobian[i, j] = _derivatives.ComputePartialDerivative( _parameters[j], 1, _functionMatrix[i, 0], listanudos1[i], variable1, _parameters);
                }
            
            }

            Matrix newXs = _x0 - _jacobian.SolveFor(_functionMatrix);
            
            for (int i = 0; i < numberOfFunctions; i++)
            {
                _parameters[i].Value = newXs[i, 0];
            }
       
        }

         
    }
}
